unit tags;
{$IFDEF FPC}
{$MODE DELPHI}
{$ENDIF}
interface
uses Bass, SysUtils;
const _ID3 = 1;
      _APE = 2;
      _BEX = 3;
      _WAV = 4;
      _MP4 = 5;
      _OGG = 6;
type Tf_info =
record
   filetype: byte;
   tags: pointer;
   file_path: string;
   length: Float;
end;

Type PL_Tags = record
  title: string;
  album: string;
  artist: string;
  year: string;
  genre: string;
  number: longint;
end;
PTf_info = ^Tf_Info;
P_ID3 = ^TAG_ID3;
P_APE = ^TAG_APE_BINARY;
P_BEXT = ^TAG_BEXT;

function Pl_Add(const flnm: string): PTf_info;
function Unname_tags(const tgs: Pointer; const bt: Byte): PL_TAGS;

implementation
uses  Adaptors, utils;
function  _DETECT(const flnm: string): byte;
var
  d: string;
  i: Cardinal;
begin
  i := length(flnm);
  d := '';
  while (i > 0) and (flnm[i] <> '.') do begin
   if (flnm[i] in ['a'..'z']) then
      d := chr(ord(flnm[i]) - (ord('a')-ord('A'))) + d
   else
    d := flnm[i] + d;
    dec(i);
  end;
  if (d = 'APE') then
    _DETECT := _APE;
  if (d = 'MP3') then
    _DETECT := _ID3;
  if (d = 'BEX') then
    _DETECT := _BEX;
  if (d = 'OGG') then
    _DETECT := _APE;
  if (d = 'M4A') then
    _DETECT := _ID3;
  if (d = 'WAV') then
    _DETECT := _BEX;
end;

function unname_Id3(const tgs: Pointer): PL_TAGS;
var
  pt: P_ID3;
  tags: Pl_TAGS;
begin
  pt := tgs;
  tags.title := pt^.title;
  tags.album := pt^.album;
  tags.year := pt^.year;
  tags.artist := pt^.artist;
  //tags.number := strtoint(pt^.id);
  Unname_ID3 := tags;
end;

function Unname_APE(const tgs: Pointer): PL_TAGS;
var
  pt: P_APE;
  tags: PL_TAGS;
begin
  pt := tgs;
  fillchar(tags, sizeof(tags), 0);
  tags.title:= pt^.data;
  tags.number := strtoint(pt^.key);
  Unname_Ape := tags;
end;

function Unname_BEXT(const tgs: Pointer): Pl_TAGS;
var
  pt: P_BEXT;
  tags: PL_TAGS;
begin
  pt := tgs;
  fillchar(tags, sizeof(tags), 0);
  tags.title := pt^.Description;
  tags.year := pt^.OriginationDate;
  unname_BEXT := tags;
end;

function unname_tags(const tgs: Pointer; const bt: Byte): PL_TAGS;
begin
  if (tgs = nil) then
  begin
    _ERROR('NIL POINTER');
    exit;
  end;
  case bt of
    _ID3: Unname_tags := unname_Id3(tgs);
    _APE: Unname_tags := unname_APE(tgs);
    _BEX: Unname_tags := unname_BEXT(tgs);
  end;
end;


function Get_TAGS(const hndl: Hstream; const bt: Byte): Pointer;
var
  id3: P_id3;
  ape: P_APE;
  bex: P_BEXT;
  pnt: Pointer;
begin
  case bt of
    _ID3: begin
            pnt := bass_channelGetTags(hndl,BASS_TAG_ID3);
            Get_TAGs := pnt;
            exit;
          end;
    _APE: begin
            pnt := bass_channelGetTags(hndl, BASS_TAG_APE);
            Get_TAGS := pnt;
            exit;
          end;
    _BEX: begin
             pnt := Bass_channelGetTags(hndl, BASS_TAG_RIFF_BEXT);
             Get_TAGS := pnt;
             exit;
           end;
    _WAV: begin
             pnt := Bass_channelGetTags(hndl, BASS_TAG_WAVEFORMAT);
             Get_TAGS := pnt;
             exit;
           end;
    _OGG: begin
             pnt := Bass_channelGetTags(hndl, BASS_TAG_OGG);
             Get_TAGS := pnt;
             exit;
           end;
    _MP4: begin
             pnt := Bass_channelGetTags(hndl, BASS_TAG_MP4);
             Get_TAGS := pnt;
             exit;
           end;
  end;
end;

function Pl_Add(const flnm: string): PTf_Info;
var
  id3tag: TAG_ID3;
  d_b: Byte;
  File_Info: Tf_Info;
  hndl: Hstream;
begin
  hndl := create_channel(flnm, true);
  if (hndl = 0) then
  begin
    _ERROR('ERROR HANDLE ' );
    Pl_add := nil;
    exit;
  end;
  File_Info.length := Get_Length(hndl);
  File_Info.file_path := flnm;
  File_Info.filetype := _DETECT(flnm);
  FIle_Info.tags := Get_TAGS(hndl, File_Info.filetype);
  Terminate_Channel(hndl);
  PL_Add := @File_INFO;
end;

end.